package com.knezevic.realestate.pages;

import com.knezevic.realestate.Advert;
import com.knezevic.realestate.Identifiable;
import com.knezevic.realestate.Member;
import com.knezevic.realestate.TypeOfAdvert;
import com.knezevic.realestate.TypeOfRealEstate;
import com.knezevic.realestate.beans.AdvertBean;
import com.knezevic.realestate.beans.RealEstateBean;
import com.knezevic.realestate.service.Adverts;
import com.knezevic.realestate.service.Members;
import com.knezevic.realestate.service.RealEstates;
import com.knezevic.realestate.util.AdvertComparatorByDate;
import com.knezevic.realestate.util.Formats;
import java.text.Format;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.annotations.Inject;

public class Home {

    @Inject
    private RealEstates realEstates;
    @Inject
    private Members members;
    @Property
    private Member member;
    @Inject
    private Adverts adverts;
    @Persist
    private Collection<Advert> allAdverts;
    @Property
    @Persist(value = "flash")
    private String message;
    private AdvertBean advert;
    @Persist
    private long vAdvertId;
    private AdvertBean vAdvert;
    @Persist
    private long eAdvertId;
    private AdvertBean eAdvert;
    private AdvertBean lAdvert;
    @InjectPage
    private CreateAdvert createAdvert;
    @Persist
    @Property
    private AdvertBean ad;
    @Property
    private double priceFrom;
    @Property
    private double priceTo;
    @Property
    private double quadratureFrom;
    @Property
    private double quadratureTo;
    @Property
    private String location;
    @Property
    private TypeOfAdvert typeOfAdvert;
    @Property
    private TypeOfRealEstate typeOfRealEstate;
    @InjectPage
    private Home home;
    @InjectPage
    private EditProfile editProfile;
    @InjectComponent
    private Zone zone;
    @Persist
    @Property
    private List<Advert> latestAdverts;
    @Persist
    private long id;
    @Persist
    private int zoneStatus;
    @Persist(value = "flash")
    @Property
    private boolean editAdvertTest;
    @Persist(value = "flash")
    @Property
    private boolean viewAdvertTest;

    public ValueEncoder getAdvertEncoder() {
        return new ValueEncoder<Advert>() {

            public String toClient(Advert value) {
                Long key = Identifiable.class.cast(value).getID();
                return key.toString();
            }

            public Advert toValue(String clientValue) {
                Long key = new Long(clientValue);
                for (Advert advert : adverts.retrieve()) {
                    if (Identifiable.class.cast(advert).getID() == (key)) {
                        return advert;
                    }
                }
                throw new IllegalArgumentException("Received key \"" + clientValue
                        + "\" which has no counterpart in this collection: ");
            }
        };
    }

    public void onActivate(long id) {
        member = members.retrieve(id);
        latestAdverts = new LinkedList<Advert>();
        if (vAdvert == null) {
            if (getvAdvertId() == 0) {
                vAdvert = new AdvertBean();
            } else {
                Advert a = adverts.retrieve(getvAdvertId());
                vAdvert = new AdvertBean();
                vAdvert.setConfirmed(a.isConfirmed());
                vAdvert.setId(getvAdvertId());
                vAdvert.setDate(a.getDate());
                vAdvert.setMember(a.getMember());
                vAdvert.setRealEstate(a.getRealEstate());
                vAdvert.setTypeOfAdvert(a.getTypeOfAdvert());
            }



        }
        if (geteAdvert() == null) {
            if (geteAdvertId() == 0) {
                eAdvert = new AdvertBean();
            } else {

                Advert a = adverts.retrieve(geteAdvertId());
                seteAdvert(new AdvertBean());
                geteAdvert().setConfirmed(a.isConfirmed());
                geteAdvert().setId(geteAdvertId());
                geteAdvert().setDate(a.getDate());
                geteAdvert().setMember(a.getMember());
                geteAdvert().setRealEstate(a.getRealEstate());
                geteAdvert().setTypeOfAdvert(a.getTypeOfAdvert());
            }
        }
        List<Advert> la = new LinkedList<Advert>();
        for (Advert advert1 : adverts.retrieve()) {
            if (advert1.isConfirmed()) {
                la.add(advert1);
            }
        }

        Collections.sort(la, new AdvertComparatorByDate());
        for (int i = 0; i < 5; i++) {
            latestAdverts.add(la.get(i));
        }

    }

    public long onPassivate() {
        if (member == null) {
            return id;
        }
        return Identifiable.class.cast(member).getID();
    }

    public void onSubmit() {
    }

    public Object onSubmitFromForm1() {
        List<Advert> la = new LinkedList<Advert>();
        CharSequence cs;
        double priceF = priceFrom;
        double priceT = priceTo;
        double quadratureF = quadratureFrom;
        double quadratureT = quadratureTo;

        if (priceF > priceT || priceF < 0 || quadratureF > quadratureT || quadratureF < 0) {
            message = "Wrong search parameters entered! please try again!";
            home.setCurentMember(member);
            home.setAllAdverts(la);
            return home;
        }
        if (location != null) {
            cs = location.toLowerCase().toString();
            for (Advert advert : adverts.retrieve()) {
                if (advert.getRealEstate().getLocation().toLowerCase().contains(cs)
                        && advert.getTypeOfAdvert().equals(typeOfAdvert)
                        && advert.getRealEstate().getTypeOfRealEstate().equals(typeOfRealEstate)
                        && priceF <= advert.getRealEstate().getPrice()
                        && advert.getRealEstate().getPrice() <= priceT
                        && quadratureF <= advert.getRealEstate().getSquareMeters()
                        && advert.getRealEstate().getSquareMeters() <= quadratureT) {
                    la.add(advert);
                }

            }
            if (la.isEmpty()) {
                message = "No search result!";
                home.setCurentMember(member);
                home.setAllAdverts(la);
                return home;
            } else {
                home.setCurentMember(member);
                home.setAllAdverts(la);
                return home;
            }
        } else {
            for (Advert advert : adverts.retrieve()) {
                if (advert.getTypeOfAdvert().equals(typeOfAdvert)
                        && advert.getRealEstate().getTypeOfRealEstate().equals(typeOfRealEstate)
                        && priceF <= advert.getRealEstate().getPrice()
                        && advert.getRealEstate().getPrice() <= priceT
                        && quadratureF <= advert.getRealEstate().getSquareMeters()
                        && advert.getRealEstate().getSquareMeters() <= quadratureT) {
                    la.add(advert);
                }

            }
            if (la.isEmpty()) {
                message = "No search result!";
                home.setCurentMember(member);
                home.setAllAdverts(la);

                return home;
            } else {
                home.setCurentMember(member);
                home.setAllAdverts(la);
                return home;
            }
        }

    }

    void onActionFromViewAdvert(long advertId) {
        setvAdvertId(advertId);
        viewAdvertTest = true;
        onSubmit();
    }

    void onActionFromViewLatestAdverts(long id) {
        Advert a = adverts.retrieve(id);
        vAdvert = new AdvertBean();
        vAdvert.setConfirmed(a.isConfirmed());
        vAdvert.setId(id);
        vAdvert.setDate(a.getDate());
        vAdvert.setMember(a.getMember());
        vAdvert.setRealEstate(a.getRealEstate());
        vAdvert.setTypeOfAdvert(a.getTypeOfAdvert());
        viewAdvertTest = true;
        vAdvertId = id;
        onSubmit();
    }

    Object onActionFromMyAdverts() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.getMember().equals(member) && a.isConfirmed()) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        zoneStatus = 1;
        return zone;
    }

    Object onActionFromMyAdvertsSelling() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.getMember().equals(member) && a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Selling)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 4;
        return zone;
    }

    Object onActionFromMyAdvertsRenting() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.getMember().equals(member) && a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Renting)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 3;
        return zone;
    }

    Object onActionFromMyAdvertsBuying() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.getMember().equals(member) && a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Buying)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 2;
        return zone;
    }

    Object onActionFromShowAllAdvertsSelling() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Selling)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 8;
        return zone;
    }

    Object onActionFromShowAllAdvertsRenting() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Renting)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 7;
        return zone;
    }

    Object onActionFromShowAllAdvertsBuying() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.isConfirmed() && a.getTypeOfAdvert().equals(TypeOfAdvert.Buying)) {
                newList.add(a);
            }
        }
        setAllAdverts(newList);
        if (newList.isEmpty()) {
            message = "No result!";
        }
        zoneStatus = 6;
        return zone;
    }

    Object onActionFromShowAllAdverts() {
        message = "";
        List<Advert> newList = new LinkedList<Advert>();
        for (Advert a : adverts.retrieve()) {
            if (a.isConfirmed()) {
                newList.add(a);
            }
        }

        zoneStatus = 5;
        setAllAdverts(newList);
        return zone;
    }

    public void onActionFromEditAdvert(long advertId) {
        message = "";
        if (adverts.retrieve(advertId).getMember().equals(member)) {
            seteAdvertId(advertId);
            editAdvertTest = true;
            onSubmit();
        } else {
            message = "You can not edit someone elses advert! Thank you!";
            onSubmit();
        }

    }

    Object onActionFromDeleteAdvert(long id) {
        message = "";
        Advert ad = adverts.retrieve(id);
        if (ad.getMember().equals(member)) {
            ad.setConfirmed(false);
            adverts.update(ad);
            refresh(zoneStatus);
            message = "You have successfully deleted you advert!";
            return zone.getBody();
        } else {
            message = "You can not delete someone elses advert! Thank you!";
            return zone;
        }

    }

    Object onActionFromCreateNewAdvert() {
        createAdvert.setMember(member);
        return createAdvert;
    }

    public long getID() {
        return id;
    }

    /**
     * @return the member
     */
    public Member getCurentMember() {
        return member;
    }

    /**
     * @param member the member to set
     */
    public void setCurentMember(Member curentMember) {
        this.member = curentMember;
    }

    /**
     * @return the allAdverts
     */
    public Collection<Advert> getAllAdverts() {
        return allAdverts;
    }

    /**
     * @param allAdverts the allAdverts to set
     */
    public void setAllAdverts(Collection<Advert> allAdverts) {
        this.allAdverts = allAdverts;
    }

    /**
     * @return the advert
     */
    public AdvertBean getAdvert() {
        return advert;
    }

    /**
     * @param advert the advert to set
     */
    public void setAdvert(AdvertBean advert) {
        this.advert = advert;
    }

    public Format getDateFormat() {
        return Formats.getDateFormat();
    }

    Object onActionFromLogout() {
        return Login.class;
    }
    /**
     * @return the lAdvert
     */
    public AdvertBean getlAdvert() {
        return lAdvert;
    }

    /**
     * @param lAdvert the lAdvert to set
     */
    public void setlAdvert(AdvertBean lAdvert) {
        this.lAdvert = lAdvert;
    }

    /**
     * @param id the id to set
     */
    public void setID(long id) {
        this.id = id;
    }

    private Object refresh(int status) {
        switch (status) {
            case 1:
                return onActionFromMyAdverts();
            case 2:
                return onActionFromMyAdvertsBuying();
            case 3:
                return onActionFromMyAdvertsRenting();
            case 4:
                return onActionFromMyAdvertsSelling();
            case 5:
                return onActionFromShowAllAdverts();
            case 6:
                return onActionFromShowAllAdvertsBuying();
            case 7:
                return onActionFromShowAllAdvertsRenting();
            case 8:
                return onActionFromShowAllAdvertsSelling();
            default:
                return null;
        }
    }

    public Object onSubmitFromForm2() {
        RealEstateBean r = (RealEstateBean) geteAdvert().getRealEstate();
        
        realEstates.update(r);
        adverts.update(geteAdvert());
        message = "You have successfully saved changes to your ad!";
       
        return null;
    }

    /**
     * @return the vAdvert
     */
    public AdvertBean getvAdvert() {
        return vAdvert;
    }

    /**
     * @param vAdvert the vAdvert to set
     */
    public void setvAdvert(AdvertBean vAdvert) {
        this.vAdvert = vAdvert;
    }

    /**
     * @return the eAdvert
     */
    public AdvertBean geteAdvert() {
        return eAdvert;
    }

    /**
     * @param eAdvert the eAdvert to set
     */
    public void seteAdvert(AdvertBean eAdvert) {
        this.eAdvert = eAdvert;
    }

    /**
     * @return the eAdvertId
     */
    public long geteAdvertId() {
        return eAdvertId;
    }

    /**
     * @param eAdvertId the eAdvertId to set
     */
    public void seteAdvertId(long eAdvertId) {
        this.eAdvertId = eAdvertId;
    }

    /**
     * @return the vAdvertId
     */
    public long getvAdvertId() {
        return vAdvertId;
    }

    /**
     * @param vAdvertId the vAdvertId to set
     */
    public void setvAdvertId(long vAdvertId) {
        this.vAdvertId = vAdvertId;
    }
}
